#ifndef LUCNX_ACPI_H
#define LUCNX_ACPI_H

#include <Lucnx/types.h>

typedef struct acpi_pointer
{
    char signatrue[8];
    u8 checksum;
    char oem_id[6];
    u8 revision;
    u32 rsdt_address;
    u32 length;
    u64 xsdt_address;
    u8 extened_checksum;
    u8 reserved[3];
}_packed acpi_pointer;

typedef struct acpi_desc_header
{
    char signature[4];
    u32 length;
    u8 revision;
    u8 checksum;
    char oem_id[6];
    u64 oem_table_id;
    u32 oem_revision;
    u32 creator_id;
    u32 creator_revision;
}_packed acpi_desc_header;

typedef struct acpi_address_t
{
    u8 address_space;
    u8 bit_width;
    u8 bit_offset;
    u8 access_size;
    u32 address[2];
}_packed acpi_address_t;

typedef struct rsdt_t
{
    acpi_desc_header header;
    u32 entry;
}_packed rsdt_t;

typedef struct fadt_t
{
    acpi_desc_header header;
    u32 FirmwareCtrl;
    u32 Dsdt;

    // field used in ACPI 1.0; no longer in use, for compatibility only
    u8 Reserved;

    u8 PreferredPowerManagementProfile;
    u16 SCI_Interrupt;
    u32 SMI_CommandPort;
    u8 AcpiEnable;
    u8 AcpiDisable;
    u8 S4BIOS_REQ;
    u8 PSTATE_Control;
    u32 PM1aEventBlock;
    u32 PM1bEventBlock;
    u32 PM1aControlBlock;
    u32 PM1bControlBlock;
    u32 PM2ControlBlock;
    u32 PMTimerBlock;
    u32 GPE0Block;
    u32 GPE1Block;
    u8 PM1EventLength;
    u8 PM1ControlLength;
    u8 PM2ControlLength;
    u8 PMTimerLength;
    u8 GPE0Length;
    u8 GPE1Length;
    u8 GPE1Base;
    u8 CStateControl;
    u16 WorstC2Latency;
    u16 WorstC3Latency;
    u16 FlushSize;
    u16 FlushStride;
    u8 DutyOffset;
    u8 DutyWidth;
    u8 DayAlarm;
    u8 MonthAlarm;
    u8 Century;

    // reserved in ACPI 1.0; used since ACPI 2.0+
    u16 BootArchitectureFlags;

    u8 Reserved2;
    u32 Flags;

    // 12 byte structure; see below for details
    acpi_address_t ResetReg;

    u8 ResetValue;
    u8 Reserved3[3];

    // 64bit pointers - Available on ACPI 2.0+
    u32 X_FirmwareControl[2];
    u32 X_Dsdt[2];

    acpi_address_t X_PM1aEventBlock;
    acpi_address_t X_PM1bEventBlock;
    acpi_address_t X_PM1aControlBlock;
    acpi_address_t X_PM1bControlBlock;
    acpi_address_t X_PM2ControlBlock;
    acpi_address_t X_PMTimerBlock;
    acpi_address_t X_GPE0Block;
    acpi_address_t X_GPE1Block;
}_packed fadt_t;

int acpi_shutdown();
void acpi_init();

#endif